<template>
    <el-form ref="formRef" :rules="rules" :model="formData" label-width="120px">
        <!-- 邮件配置 -->
        <el-card shadow="never" class="!border-none">
            <div class="text-xl font-medium mb-[20px]">参数配置</div>
            <el-form-item label="功能开关" prop="status">
                <div>
                    <el-radio-group v-model="formData.status">
                        <el-radio :value="1">开启</el-radio>
                        <el-radio :value="0">关闭</el-radio>
                    </el-radio-group>
                    <div class="form-tips">关闭阅读功能后, 用户端将无法上传文件。</div>
                </div>
            </el-form-item>
            <el-form-item label="自动总结" prop="auto_abstract">
                <div>
                    <el-radio-group v-model="formData.auto_abstract">
                        <el-radio :value="1">开启</el-radio>
                        <el-radio :value="0">关闭</el-radio>
                    </el-radio-group>
                    <div class="form-tips">文档上传完毕后, 自动开始进行总结。</div>
                </div>
            </el-form-item>
            <el-form-item label="检索重排" prop="ranking_status">
                <div>
                    <el-radio-group v-model="formData.ranking_status">
                        <el-radio :value="1">开启</el-radio>
                        <el-radio :value="0">关闭</el-radio>
                    </el-radio-group>
                    <div class="form-tips">功能开启后请在下发配置重排模型。</div>
                </div>
            </el-form-item>
            <el-form-item label="收费方式" prop="charge_method">
                <div>
                    <el-radio-group v-model="formData.charge_method">
                        <el-radio :value="0">免费</el-radio>
                        <el-radio :value="1">模型</el-radio>
                        <el-radio :value="2">固定</el-radio>
                    </el-radio-group>
                    <div class="form-tips">文档对话总结等场景收费的方式。</div>
                </div>
            </el-form-item>
            <el-form-item v-if="formData.charge_method === 2" label="固定收费" prop="charge_amount">
                <div>
                    <el-input
                        type="number"
                        v-model="formData.charge_amount"
                        :min="0"
                        :max="99999999"
                    />
                    <div class="form-tips">当收费方式切换到固定收费时生效。</div>
                </div>
            </el-form-item>
            <el-form-item v-if="formData.ranking_status" label="重排模型" prop="ranking_models">
                <template #label>
                    <span class="mr-1">重排模型</span>
                    <el-tooltip effect="dark" placement="right">
                        <icon name="el-icon-InfoFilled" />
                        <template #content>
                            <p>重排模型 即 对通过语义或混合检索的结果进行重新排序来提高精准度。</p>
                            <br />
                            <p>1. 注意: 需要把重排模型状态打开才会使用重排模型。</p>
                            <p>2. 选择好重排模型后，请到 【密钥设置 -> 重排模型】添加对应的密钥。</p>
                        </template>
                    </el-tooltip>
                </template>
                <div class="w-[240px]">
                    <models-select
                        v-model="formData.ranking_models"
                        type="ranking"
                    />
                </div>
            </el-form-item>
            <el-form-item label="训练模型" prop="vector_models">
                <template #label>
                    <span class="mr-1">训练模型</span>
                    <el-tooltip effect="dark" placement="right">
                        <icon name="el-icon-InfoFilled" />
                        <template #content>
                            <p>训练模型 即 『向量模型』用于把文档内容向量化。</p>
                            <br />
                            <p>1. 请不要随意修改向量模型，这可能会导致旧文件数据出错无法使用。</p>
                            <p>2. 选择好向量模型后，请到 【密钥设置 -> 向量模型】添加对应的密钥。</p>
                        </template>
                    </el-tooltip>
                </template>
                <div class="w-[240px]">
                    <models-select
                        v-model="formData.vector_models"
                        type="vector"
                    />
                </div>
            </el-form-item>
            <el-form-item label="搜索模式" prop="search_mode">
                <template #label>
                    <span class="mr-1">搜索模式</span>
                    <el-tooltip effect="dark" placement="right">
                        <icon name="el-icon-InfoFilled" />
                        <template #content>
                            <p>不同的检索模式，效果不一样，根据自身情况选择合适的模式。</p>
                        </template>
                    </el-tooltip>
                </template>
                <el-select v-model="formData.mode" size="large" class="!w-[240px]">
                    <template #prefix>
                        <div class="flex items-center">
                            <el-image
                                class="w-[16px] h-[16px] mr-1.5"
                                :src="searchModeLists[searchModelDict[formData.mode]].icon"
                            />
                        </div>
                    </template>
                    <el-option
                        v-for="(item, index) in searchModeLists"
                        :key="index"
                        :label="item.name"
                        :value="item.key"
                    >
                        <div class="flex items-center">
                            <el-image class="w-[16px] h-[16px] mr-2" :src="item.icon" />
                            <span>{{ item.name }}</span>
                            <el-tooltip
                                effect="dark"
                                :content="item.tips"
                                placement="top"
                            >
                                <icon name="el-icon-InfoFilled" class="ml-2" />
                            </el-tooltip>
                        </div>
                    </el-option>
                </el-select>
            </el-form-item>
            <el-form-item label="引用上限" prop="search_tokens" required>
                <template #label>
                    <span class="mr-1">引用上限</span>
                    <el-tooltip effect="dark" placement="right">
                        <icon name="el-icon-InfoFilled" />
                        <template #content>
                            <p>该参数表示单次文档从知识库检索最大的Tokens数量</p>
                            <p>说明: 引用越多意味着所需消耗的token越多</p>
                            <p>注意: 切记不要超出模型的最大token限制</p>
                        </template>
                    </el-tooltip>
                </template>
                <div class="w-[400px]">
                    <el-slider
                        v-model="formData.search_tokens"
                        :min="100"
                        :max="20000"
                        :step="1"
                        show-input
                    />
                </div>
            </el-form-item>
            <el-form-item label="最低相似度" prop="search_similar" required>
                <template #label>
                    <span class="mr-1">最低相似度</span>
                    <el-tooltip effect="dark" placement="right">
                        <icon name="el-icon-InfoFilled" />
                        <template #content>
                            <p>语义检索的精度，提问检索的内容需要达到该精度才会被引用</p>
                            <br />
                            <p>1. 高语义相似度(>=0.8): 会检索相关性高的知识，会更准确，同时也容易未命中。</p>
                            <p>2. 低语义相似度(如0.4): 检索范围更大，更容易匹配知识，但可能回答会不准确。</p>
                            <p>3. 不同的向量模型检索相似度不一样，具体情况请自行测试最优数值。</p>
                        </template>
                    </el-tooltip>
                </template>
                <div class="w-[400px]">
                    <el-slider
                        v-model="formData.search_similar"
                        :min="0"
                        :max="1"
                        :step="0.001"
                        show-input
                    />
                </div>
            </el-form-item>
            <el-form-item v-if="formData.ranking_status" label="重排相似度" prop="ranking_score" required>
                <template #label>
                    <span class="mr-1">重排相似度</span>
                    <el-tooltip effect="dark" placement="right">
                        <icon name="el-icon-InfoFilled" />
                        <template #content>
                            <p>重排模型排序后的分数，只有达到该分数的内容才会被音乐</p>
                            <br />
                            <p>1. 如果启用了重排模型，则使用该重排相似度作为参考值，而不是语义检索的最低相似度。</p>
                            <p>2. 建议你在使用 混合检索 或 全文检索 时开启重排模型，来提升你的检索精准度。</p>
                        </template>
                    </el-tooltip>
                </template>
                <div class="w-[400px]">
                    <el-slider
                        v-model="formData.ranking_score"
                        :min="0"
                        :max="1"
                        :step="0.001"
                        show-input
                    />
                </div>
            </el-form-item>
            <el-form-item prop="chat_avatar">
                <material-picker v-model="formData.chat_avatar" />
                <template v-slot:label>
                    <span class="mr-1">对话的头像</span>
                    <el-tooltip
                        placement="right"
                        content='建议尺寸: 64 * 64像素, 支持格式 [ jpg、jpeg、png、gif ]'
                    >
                        <icon name="el-icon-InfoFilled" />
                    </el-tooltip>
                </template>
            </el-form-item>
        </el-card>

        <!-- 保存按钮 -->
        <el-card shadow="never" class="!border-none mt-4">
            <el-button
                v-perms="['apply:docs:setting:save']"
                :loading="loading"
                type="primary"
                @click="handleSubmit"
            >保存配置</el-button>
        </el-card>
    </el-form>
</template>

<script setup lang="ts">
import feedback from '@/utils/feedback'
import docsSettingApi from '@/api/apply/docs/setting'
import semsIcon from '@/assets/image/search_semantics.png'
import fullIcon from '@/assets/image/search_full.png'
import mixIcon from '@/assets/image/search_mix.png'

const loading = ref(false)
const formRef = ref()
const formData = reactive({
    status: 0,
    auto_abstract: 0,
    charge_method: 0,
    charge_amount: 0,
    ranking_status: 0,
    ranking_models:'',
    vector_models:'',
    chat_avatar:'',
    context_num: 3,
    mode: 'similar',
    search_tokens: 5000,
    search_similar: 0.4,
    ranking_score: 0.4
})

const searchModelDict: any = {'similar': 0, 'full': 1, 'mix': 2}
const searchModeLists = [
    {
        key: 'similar',
        name: '语义检索',
        tips: '使用向量进行文本相关查询',
        icon: semsIcon,
    },
    {
        key: 'full',
        name: '全文检索',
        tips: '使用传统的全文检索, 适合查找一些关键词和主谓语特殊的数据',
        icon: fullIcon,
    },
    {
        key: 'mix',
        name: '混合检索',
        tips: '使用向量检索与全文检索的综合结果并重新进行排序',
        icon: mixIcon
    }
]

// 表单验证
const rules = {
    'status': [
        { required: true, message: '请选择功能状态', trigger: 'blur' }
    ],
    'ranking_status': [
        { required: true, message: '请选择检索重排状态', trigger: 'blur' }
    ],
    'auto_abstract': [
        { required: true, message: '请选择是否自动总结', trigger: 'blur' }
    ],
    'charge_method': [
        { required: true, message: '请选择收费的方式', trigger: 'blur' }
    ],
    'charge_amount': [
        { required: true, message: '请输入固定收费数量', trigger: 'blur' }
    ],
    'search_mode': [
        { required: true, message: '请选择搜索模型', trigger: 'blur' }
    ],
    'vector_models': [
        { required: true, message: '请选择训练模型', trigger: 'blur' }
    ],
    'ranking_models': [
        { required: true, message: '请选择重排模型', trigger: 'blur' }
    ],
    'chat_avatar': [
        { required: true, message: '请设置对话头像', trigger: 'blur' }
    ]
}

/**
 * 查询配置参数
 */
const queryConfigs = async (): Promise<void> => {
    const data = await docsSettingApi.detail()
    Object.assign(formData, data)
}

/**
 * 提交修改参数
 */
const handleSubmit = async (): Promise<void> => {
    await formRef.value?.validate().then(async () => {
        loading.value = true
        await docsSettingApi.save(formData)
            .finally(() => {
                setTimeout(() => {
                    loading.value = false
                }, 500)
            })

        await queryConfigs()
        feedback.msgSuccess('保存成功')
    }).catch(() => {})
}

onMounted(async () => {
    await queryConfigs()
})
</script>
